#include "sLocalizationResource.h"

namespace sgui
{
namespace res
{

// --------------------------------------------- sLocalizationItem --------------------------------------------------
        
sLocalizationItem::sLocalizationItem(sGUI& gui, const std::wstring& name, const u32& langs) :
    sResourceItem(gui, name),
    m_langsCount(langs)
{
    m_items.resize(langs);
}

void sLocalizationItem::load(const db::Record &file)
{
    if (file.getSize() == m_langsCount)
    {
        for (u32 i = 0; i < m_langsCount; i++)
        {
            m_items[i] = file[i].GetAsString();
        }
    }
}

void sLocalizationItem::save(db::Record &file)
{
    file.setSize(m_langsCount);
    for (u32 i = 0; i < m_langsCount; i++)
    {
        file[i].Set(m_items[i]);
    }
}

void sLocalizationItem::clear()
{
    m_items.clear();
}

std::wstring* sLocalizationItem::operator[](const u32 langId)
{
    if (langId < m_langsCount)
    {
        return &m_items[langId];
    }
    return NULL;
}


#ifdef _EDITOR
bool sLocalizationItem::OnEvent(const obs::sEvent& event)
{
    switch (event.getID())
    {
        case obs::EVID_ADD_ITEM:
        {
            CAST_EVENT(ev, sAddLangEvent);
            m_items.resize(ev.m_newSize);
            break;
        }
        case obs::EVID_REMOVE_ITEM:
        {
            CAST_EVENT(ev, sRemoveLangEvent);
            m_items.erase(m_items.begin() + ev.m_removeIdx);
            break;
        }
    }
    return false;
}
#endif
        
// ------------------------------------------- sLocalizationResource ------------------------------------------------

const std::wstring sLocalizationResource::RESOURCE_NAME = L"LOC";

void sLocalizationResource::load(const db::Record &file)
{
	sResource::load(file);
    const db::Record &langs = file[L"langs"];
    m_langsCount = langs.getSize();
    for (db::Record::const_iterator i = langs.childBegin(); i != langs.childEnd(); i++)
    {
        db::Record* item = i->second;
        const std::wstring& name = i->first;
        m_langs[name] = item->GetAsInt();
    }

    const db::Record &strings = file[L"strings"];
    for (db::Record::const_iterator i = strings.childBegin(); i != strings.childEnd(); i++)
    {
        sLocalizationItem &str = addString(i->first);
        str.load(*i->second);
    }

}

void sLocalizationResource::save(db::Record &file)
{
	sResource::save(file);
    db::Record &langs = file[L"langs"];
    for (std::map<std::wstring, u32>::iterator it = m_langs.begin(); it != m_langs.end(); it++)
    {
        langs[it->first].Set(it->second);
    }

    db::Record &strings = file[L"strings"];
    
    for (std::map<std::wstring, sLocalizationItem*>::iterator it = m_strings.begin(); it != m_strings.end(); it++)
    {
        it->second->save(strings[it->first]);
    }
}

void sLocalizationResource::clear()
{
    for (CONTAINER_WRAPPER(sLocalizationItem)::iterator it = m_strings.begin(); it != m_strings.end(); it++)
    {
#ifdef _EDITOR
        unregisterObserver(it->second);
#endif
        delete it->second;
    }
    m_strings.clear();
    m_langs.clear();
    m_langsCount = 0;
}

CONTAINER_WRAPPER(sLocalizationItem)& sLocalizationResource::getStrings()
{
    return m_strings;
}

std::wstring* sLocalizationResource::getString(const std::wstring& name, const u32 langId)
{
    sLocalizationItem* item = (*this)[name];
    if (item)
    {
        return (*item)[langId];
    }
    return NULL;
}

std::wstring* sLocalizationResource::getString(const std::wstring& name, const std::wstring& langName) 
{
    std::map<std::wstring, u32>::iterator it = m_langs.find(langName);
    if (it != m_langs.end())
    {
        return getString(name, it->second);
    }
    return NULL;
}
        
sLocalizationItem* sLocalizationResource::operator[](const std::wstring name)
{
    return m_strings[name];
}

#ifdef _EDITOR
void sLocalizationResource::exportRTTI(rtti::sInfoList& list)
{
	sResource::exportRTTI(list);

}

const u32 sLocalizationResource::addLang(const std::wstring& name)
{
    std::map<std::wstring, u32>::iterator it = m_langs.find(name);
    if (it == m_langs.end())
    {
        m_langs[name] = m_langsCount++;
        notify(new obs::sAddLangEvent(m_langsCount), obs::EVTAG_LANG);
    }
    return m_langsCount;
}

void sLocalizationResource::removeLang(const std::wstring& name)
{
    std::map<std::wstring, u32>::iterator it = m_langs.find(name);
    if (it != m_langs.end())
    {
        const u32 langIdx = it->second;
        m_langs.erase(it);
        notify(new obs::sRemoveLangEvent(langIdx), obs::EVTAG_LANG);
        
        for (std::map<std::wstring, u32>::iterator i = m_langs.begin(); i != m_langs.end(); i++)
        {
            if (i->second > langIdx)
                i->second--;

        }
        m_langsCount--;
    }
}
        
sLocalizationItem& sLocalizationResource::addString(const std::wstring& name)
{
    sLocalizationItem* item = new sLocalizationItem(getGui(), name, m_langsCount);
    m_strings.add(item);
    registerObserver(item, obs::EVTAG_LANG);
    return *item;
}
        
void sLocalizationResource::removeString(const std::wstring& name)
{
    sLocalizationItem* it = m_strings[name];
    if (it)
    {
        unregisterObserver(it);
        m_strings.remove(name);
    }
}
#endif

sLocalizationResource::sLocalizationResource(sGUI& gui, const std::wstring& name) :
	sResource(gui, name),
	m_strings(gui),
    m_langsCount(0)
{
	//
}

sLocalizationResource::~sLocalizationResource()
{
    //
}

};
};